home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH21 / RECEIVE.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-07-26  |  9.0 KB  |  366 lines

  1. ; RECEIVE.ASM
  2. ;
  3. ; This program is the receiver portion of the programs that transmit files
  4. ; across a Laplink compatible parallel cable.
  5. ;
  6. ; This program assumes that the user want to use LPT1: for transmission.
  7. ; Adjust the equates, or read the port from the command line if this
  8. ; is inappropriate.
  9.  
  10.         .286
  11.         .xlist
  12.         include     stdlib.a
  13.         includelib    stdlib.lib
  14.         .list
  15.  
  16.  
  17. dseg        segment    para public 'data'
  18.  
  19. TimeOutConst    equ    100            ;About 1 min on 66Mhz 486.
  20. PrtrBase    equ    8            ;Offset to LPT1: adrs.
  21.  
  22. MyPortAdrs    word    ?            ;Holds printer port address.
  23. FileHandle    word    ?            ;Handle for output file.
  24. FileBuffer    byte    512 dup (?)        ;Buffer for incoming data.
  25.  
  26. FileSize    dword    ?            ;Size of incoming file.
  27. FileName    byte    128 dup (0)        ;Holds filename
  28.  
  29. dseg        ends
  30.  
  31. cseg        segment    para public 'code'
  32.         assume    cs:cseg, ds:dseg
  33.  
  34.  
  35. ; TestAbort-    Reads the keyboard and gives the user the opportunity to
  36. ;        hit the ctrl-C key.
  37.  
  38. TestAbort    proc    near
  39.         push    ax
  40.         mov    ah, 1
  41.         int    16h            ;See if keypress.
  42.         je    NoKeypress
  43.         mov    ah, 8            ;Read char, chk for ctrl-C
  44.         int    21h
  45. NoKeyPress:    pop    ax
  46.         ret
  47. TestAbort    endp
  48.  
  49.  
  50.  
  51. ; GetByte-    Reads a single byte from the parallel port (four bits at
  52. ;        at time).  Returns the byte in AL.
  53.  
  54. GetByte        proc    near
  55.         push    cx
  56.         push    dx
  57.  
  58. ; Receive the L.O. Nibble.
  59.  
  60.         mov    dx, MyPortAdrs
  61.         mov    al, 10h            ;Signal not busy.
  62.         out    dx, al
  63.  
  64.         inc    dx            ;Point at status port
  65.  
  66. W4DLp:        mov    cx, 10000
  67. Wait4Data:    in    al, dx            ;See if data available.
  68.         test    al, 80h            ; (bit 7=0 if data available).
  69.         loopne    Wait4Data
  70.         je    DataIsAvail        ;Is data available?
  71.         call    TestAbort        ;If not, check for ctrl-C.
  72.         jmp    W4DLp
  73.  
  74. DataIsAvail:    shr    al, 3            ;Save this four bit package
  75.         and    al, 0Fh            ; (This is the L.O. nibble
  76.         mov    ah, al            ; for our byte).
  77.  
  78.         dec    dx            ;Point at data register.
  79.         mov    al, 0            ;Signal data taken.
  80.         out    dx, al
  81.  
  82.         inc    dx            ;Point at status register.
  83. W4ALp:        mov    cx, 10000
  84. Wait4Ack:    in    al, dx            ;Wait for transmitter to
  85.         test    al, 80h            ; retract data available.
  86.         loope    Wait4Ack        ;Loop until data not avail.
  87.         jne    NextNibble        ;Branch if data not avail.
  88.         call    TestAbort        ;Let user hit ctrl-C.
  89.         jmp    W4ALp
  90.  
  91. ; Receive the H.O. nibble:
  92.  
  93. NextNibble:    dec    dx            ;Point at data register.
  94.         mov    al, 10h            ;Signal not busy
  95.         out    dx, al
  96.         inc    dx            ;Point at status port
  97. W4D2Lp:        mov    cx, 10000
  98. Wait4Data2:    in    al, dx            ;See if data available.
  99.         test    al, 80h            ; (bit 7=0 if data available).
  100.         loopne    Wait4Data2        ;Loop until data available.
  101.         je    DataAvail2        ;Branch if data available.
  102.         call    TestAbort        ;Check for ctrl-C.
  103.         jmp    W4D2Lp
  104.  
  105. DataAvail2:    shl    al, 1            ;Merge this H.O. nibble
  106.         and    al, 0F0h        ; with the existing L.O.
  107.         or    ah, al            ; nibble.
  108.         dec    dx            ;Point at data register.
  109.         mov    al, 0            ;Signal data taken.
  110.         out    dx, al
  111.  
  112.         inc    dx            ;Point at status register.
  113. W4A2Lp:        mov    cx, 10000
  114. Wait4Ack2:    in    al, dx            ;Wait for transmitter to
  115.         test    al, 80h            ; retract data available.
  116.         loope    Wait4Ack2               ;Wait for data not available.
  117.         jne    ReturnData        ;Branch if ack.
  118.         call    TestAbort        ;Check for ctrl-C
  119.         jmp    W4A2Lp
  120.  
  121. ReturnData:    mov    al, ah            ;Put data in al.
  122.         pop    dx
  123.         pop    cx
  124.         ret
  125. GetByte        endp
  126.  
  127.  
  128.  
  129.  
  130. ; Synchronize-    This procedure waits until it sees all zeros on the input
  131. ;        bits we receive from the transmiting site.  Once it receives
  132. ;        all zeros, it writes all ones to the output port.  When
  133. ;        all ones come back, it writes all zeros.  It repeats this
  134. ;        process until the transmiting site writes the value 05h.
  135.  
  136. Synchronize    proc    near
  137.  
  138.         print
  139.         byte    "Synchronizing with transmitter program"
  140.         byte    cr,lf,0
  141.  
  142.         mov    dx, MyPortAdrs
  143.         mov    al, 0            ;Initialize our output port
  144.         out    dx, al            ; to prevent confusion.
  145.         mov    bx, TimeOutConst    ;Time out condition.
  146. SyncLoop:    mov    cx, 0            ;For time out purposes.
  147. SyncLoop0:    inc    dx            ;Point at input port.
  148.         in    al, dx            ;Read our input bits.
  149.         dec    dx
  150.         and    al, 78h            ;Keep only the data bits.
  151.         cmp    al, 78h            ;Check for all ones.
  152.         je    Got1s            ;Branch if all ones.
  153.         cmp    al, 0            ;See if all zeros.
  154.         loopne    SyncLoop0
  155.  
  156. ; Since we just saw a zero, write all ones to the output port.
  157.  
  158.         mov    al, 0FFh        ;Write all ones
  159.         out    dx, al
  160.  
  161. ; Now wait for all ones to arrive from the transmiting site.
  162.  
  163. SyncLoop1:    inc    dx            ;Point at status register.
  164.         in    al, dx            ;Read status port.
  165.         dec    dx            ;Point back at data register.
  166.         and    al, 78h            ;Keep only the data bits.
  167.         cmp    al, 78h            ;Are they all ones?
  168.         loopne    SyncLoop1        ;Repeat while not ones.
  169.         je    Got1s            ;Branch if got ones.
  170.  
  171. ; If we've timed out, check to see if the user has pressed ctrl-C to
  172. ; abort.
  173.  
  174.         call    TestAbort        ;Check for ctrl-C.
  175.         dec    bx            ;See if we've timed out.
  176.         jne    SyncLoop        ;Repeat if time-out.
  177.  
  178.         print
  179.         byte    "Receive: connection timed out during synchronization"
  180.         byte    cr,lf,0
  181.         clc                ;Signal time-out.
  182.         ret
  183.  
  184. ; Jump down here once we've seen both a zero and a one.  Send the two
  185. ; in combinations until we get a 05h from the transmiting site or the
  186. ; user presses Ctrl-C.
  187.  
  188. Got1s:          inc    dx            ;Point at status register.
  189.         in    al, dx            ;Just copy whatever appears
  190.         dec    dx            ; in our input port to the
  191.         shr    al, 3            ; output port until the
  192.         and    al, 0Fh            ; transmiting site sends
  193.         cmp    al, 05h            ; us the value 05h
  194.         je    Synchronized
  195.         not    al            ;Keep inverting what we get
  196.         out    dx, al            ; and send it to xmitter.
  197.         call    TestAbort        ;Check for CTRL-C here.
  198.         jmp    Got1s
  199.  
  200.  
  201. ; Okay, we're synchronized.  Return to the caller.
  202.  
  203. Synchronized:
  204.         and    al, 0Fh            ;Make sure busy bit is one
  205.         out    dx, al            ; (bit 4=0 for busy=1).
  206.         print
  207.         byte    "Synchronized with transmiting site"
  208.         byte    cr,lf,0
  209.         stc
  210.         ret
  211. Synchronize    endp
  212.  
  213.  
  214. ; GetFileInfo-    The transmitting program sends us the file length and a
  215. ;        zero terminated filename.  Get that data here.
  216.  
  217. GetFileInfo    proc    near
  218.         mov    dx, MyPortAdrs
  219.         mov    al, 10h            ;Set busy bit to zero.
  220.         out    dx, al            ;Tell xmit pgm, we're ready.
  221.  
  222. ; First four bytes contain the filesize:
  223.  
  224.         call    GetByte
  225.         mov    byte ptr FileSize, al
  226.         call    GetByte
  227.         mov    byte ptr FileSize+1, al
  228.         call    GetByte
  229.         mov    byte ptr FileSize+2, al
  230.         call    GetByte
  231.         mov    byte ptr FileSize+3, al
  232.  
  233. ; The next n bytes (up to a zero terminating byte) contain the filename:
  234.  
  235.         mov    bx, 0
  236. GetFileName:    call    GetByte
  237.         mov    FileName[bx], al
  238.         call    TestAbort
  239.         inc    bx
  240.         cmp    al, 0
  241.         jne    GetFileName
  242.  
  243.         ret
  244. GetFileInfo    endp
  245.  
  246.  
  247. ; GetFileData-    Receives the file data from the transmitting site
  248. ;        and writes it to the output file.
  249.  
  250. GetFileData    proc    near
  251.  
  252. ; First, see if we have more than 512 bytes left to go
  253.  
  254.         cmp    word ptr FileSize+2, 0        ;If H.O. word is not
  255.         jne    MoreThan512            ; zero, more than 512.
  256.         cmp    word ptr FileSize, 512        ;If H.O. is zero, just
  257.         jbe    LastBlock            ; check L.O. word.
  258.  
  259. ; We've got more than 512 bytes left to go in this file, read 512 bytes
  260. ; at this point.
  261.  
  262. MoreThan512:    mov    cx, 512                ;Receive 512 bytes
  263.         lea    bx, FileBuffer            ; from the xmitter.
  264. ReadLoop:    call    GetByte                ;Read a byte.
  265.         mov    [bx], al            ;Save the byte away.
  266.         inc    bx                ;Move on to next
  267.         loop    ReadLoop            ; buffer element.
  268.  
  269. ; Okay, write the data to the file:
  270.  
  271.         mov    ah, 40h                ;DOS write opcode.
  272.         mov    bx, FileHandle            ;Write to this file.
  273.         mov    cx, 512                ;Write 512 bytes.
  274.         lea    dx, Filebuffer            ;From this address.
  275.         int    21h
  276.         jc    BadWrite            ;Quit if error.
  277.  
  278. ; Decrement the file size by 512 bytes:
  279.  
  280.         sub    word ptr FileSize, 512        ;32-bit subtraction
  281.         sbb    word ptr FileSize, 0        ; of 512.
  282.         jmp    GetFileData
  283.  
  284. ; Process the last block, that contains 1..511 bytes, here.
  285.  
  286. LastBlock:
  287.         mov    cx, word ptr FileSize        ;Receive the last
  288.         lea    bx, FileBuffer            ; 1..511 bytes from
  289. ReadLB:        call    GetByte                ; the transmitter.
  290.         mov    [bx], al
  291.         inc    bx
  292.         loop    ReadLB
  293.  
  294.         mov    ah, 40h                ;Write the last block
  295.         mov    bx, FileHandle            ; of bytes to the
  296.         mov    cx, word ptr FileSize        ; file.
  297.         lea    dx, Filebuffer
  298.         int    21h
  299.         jnc    Closefile
  300.  
  301. BadWrite:    print
  302.         byte    "DOS error #",0
  303.         puti
  304.         print
  305.         byte    " while writing data.",cr,lf,0
  306.  
  307. ; Close the file here.
  308.  
  309. CloseFile:    mov    bx, FileHandle            ;Close this file.
  310.         mov    ah, 3Eh                ;DOS close opcode.
  311.         int    21h
  312.         ret
  313. GetFileData    endp
  314.  
  315.  
  316.  
  317. ; Here's the main program that gets the whole ball rolling.
  318.  
  319. Main        proc
  320.         mov    ax, dseg
  321.         mov    ds, ax
  322.         meminit
  323.  
  324.  
  325. ; First, get the address of LPT1: from the BIOS variables area.
  326.  
  327.         mov    ax, 40h        ;Point at BIOS variable segment.
  328.         mov    es, ax
  329.         mov    ax, es:[PrtrBase]
  330.         mov    MyPortAdrs, ax
  331.  
  332.         call    Synchronize    ;Wait for the transmitter program.
  333.         jnc    Quit
  334.  
  335.         call    GetFileInfo    ;Get file name and size.
  336.  
  337.         printf
  338.         byte    "Filename: %s\nFile size: %ld\n",0
  339.         dword    Filename, FileSize
  340.  
  341.         mov    ah, 3Ch        ;Create file.
  342.         mov    cx, 0        ;Standard attributes
  343.         lea    dx, Filename
  344.         int    21h
  345.         jnc    GoodOpen
  346.         print
  347.         byte    "Error opening file",cr,lf,0
  348.         jmp    Quit
  349.  
  350. GoodOpen:    mov    FileHandle, ax
  351.         call    GetFileData    ;Get the file's data.
  352.  
  353. Quit:        ExitPgm            ;DOS macro to quit program.
  354. Main        endp
  355.  
  356. cseg        ends
  357.  
  358. sseg        segment    para stack 'stack'
  359. stk        byte    1024 dup ("stack   ")
  360. sseg        ends
  361.  
  362. zzzzzzseg    segment    para public 'zzzzzz'
  363. LastBytes    byte    16 dup (?)
  364. zzzzzzseg    ends
  365.         end    Main
  366.